/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package DataStructuresThreads;

import Sorting.Main;
import Sorting.ThreadAuxiliary;
import com.sun.j3d.utils.geometry.Box;
import com.sun.j3d.utils.geometry.Cone;
import com.sun.j3d.utils.geometry.Sphere;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.*;
import javax.vecmath.Vector3f;

/**
 *
 * @author rafael
 */
public class ListThread extends Thread {

    public ListThread listThread = this;
    public static boolean isRunning = false;
    public static Vector3f elementPosition = new Vector3f(-0.15f, 0.0f, -0.2f);
    public static TransformGroup tgFix;

    public ListThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        execute();
    }

    private void execute() {

        try {

            Main.clearTexts();
            callListButtons();

            Main.frame.setEnabled(false);

            BranchGroup bgroup = Main.listBranchGroup();
            Main.su.addBranchGraph(bgroup);

        } finally {
            Main.isRunning = false;
            Main.clearTexts();
        }
    }

    public static void createFix() {

        BranchGroup branchGroup = new BranchGroup();

        Box fix = new Box(0.1f, 0.02f, 0.05f, Main.addAparenciaGreen());
        fix.setCapability(Sphere.ENABLE_APPEARANCE_MODIFY);
        Transform3D tfBox = new Transform3D();

        tfBox.setTranslation(new Vector3f((Main.vectorSize * 0.2f) - 0.4f, elementPosition.y, elementPosition.z));
        TransformGroup tgBox = new TransformGroup(tfBox);
        tgBox.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        tgBox.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        tgBox.addChild(fix);
        branchGroup.addChild(tgBox);

        tgFix = tgBox;
        Main.su.addBranchGraph(branchGroup);

    }

    public static void createFix(float x) {

        BranchGroup branchGroup = new BranchGroup();
        Box fix;
        if (Main.vectorSize < 5) {
            fix = new Box(0.1f * x, 0.02f, 0.05f, Main.criarAppCustom());
        } else {
            fix = new Box(0.12f * x, 0.02f, 0.05f, Main.criarAppCustom());
        }

        fix.setCapability(Sphere.ENABLE_APPEARANCE_MODIFY);
        Transform3D tfBox = new Transform3D();
        if (Main.vectorSize < 5) {
            tfBox.setTranslation(new Vector3f((Main.vectorSize * 0.2f) - 0.4f - ((x - 1) * 0.1f), elementPosition.y, elementPosition.z));
        } else if (Main.vectorSize == 7) {
            tfBox.setTranslation(new Vector3f((Main.vectorSize * 0.2f) - 0.4f - ((x - 3) * 0.12f), elementPosition.y, elementPosition.z));
        } else {
            tfBox.setTranslation(new Vector3f((Main.vectorSize * 0.2f) - 0.4f - ((x - 2) * 0.12f), elementPosition.y, elementPosition.z));
        }
        TransformGroup tgBox = new TransformGroup(tfBox);
        tgBox.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        tgBox.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        tgBox.addChild(fix);
        branchGroup.addChild(tgBox);

        tgFix = tgBox;
        Main.su.addBranchGraph(branchGroup);

    }

    public static void recreateFix(float x) {

        BranchGroup branchGroup = new BranchGroup();
        Box fix;

        fix = new Box(0.1f * x, 0.02f, 0.05f, Main.criarAppCustom());
        fix.setCapability(Sphere.ENABLE_APPEARANCE_MODIFY);

        Transform3D tfBox = new Transform3D();
        tfBox.setTranslation(new Vector3f((Main.vectorSize * 0.2f) - 0.4f - ((x + 1) * 0.1f), elementPosition.y, elementPosition.z));

        TransformGroup tgBox = new TransformGroup(tfBox);
        tgBox.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        tgBox.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        tgBox.addChild(fix);
        branchGroup.addChild(tgBox);

        tgFix = tgBox;
        Main.su.addBranchGraph(branchGroup);

    }

    public static void modifyFix() {

        TransformGroup tgModify = tgFix;

        Transform3D tfModify = new Transform3D();
        tgModify.getTransform(tfModify);
        Vector3f translationModify = new Vector3f();
        tfModify.get(translationModify);

        translationModify.x = 0.6f;

        tfModify.setTranslation(translationModify);
        tgModify.setTransform(tfModify);

    }

    public static void removeFix() {

        TransformGroup tgModify = tgFix;

        Transform3D tfModify = new Transform3D();
        tgModify.getTransform(tfModify);
        Vector3f translationModify = new Vector3f();
        tfModify.get(translationModify);

        translationModify.z = 999999f;

        tfModify.setTranslation(translationModify);
        tgModify.setTransform(tfModify);

    }

    private static void checkElementPosition(int index) {

        elementPosition.x = (index * 0.25f) - 0.4f;

    }

    public static void insertElement() {
        
        Main.textPane.setText(Main.textoListaAdd);
        

        

        String indexString = "";
        int indexNumber = -1;

        while (indexNumber < 0 || indexNumber > 9) {
            indexString = JOptionPane.showInputDialog("Qual a posição do número adicionado? Capacidade atual: " + Main.vectorCapacity);

            if (indexString == null || indexString.equals("")) {
            } else {
                indexNumber = Integer.parseInt(indexString);
            }

        }

        Main.highlightsText("  se (indice < 0 || indice > tamanho_lista) {\n", Main.textoListaAdd);
        if (indexNumber < 0 || indexNumber > Main.vectorSize) {
            Main.highlightsText("    Erro: Indice fora da lista!\n", Main.textoListaAdd);
            JOptionPane.showMessageDialog(null, "O índice não está dentro dos limites da lista atual.");
        } else {
            
            String numberString = "";
            int number = -1;

            while (number < 0 || number > 9) {
                numberString = JOptionPane.showInputDialog("Qual o número à ser adicionado?");

                if (numberString == null || numberString.equals("")) {
                } else {
                    number = Integer.parseInt(numberString);
                }

            }

            System.out.println("Vai adicionar o: " + number);
            
            if (indexNumber - 1 > -1) {
                Main.vetorNumeros[indexNumber - 1].hideRight();
            }
            
            try {
                if (Main.vetorNumeros[indexNumber] != null) {
                    Main.vetorNumeros[indexNumber].hideLeft();
                } else {
                    if (indexNumber + 1 < Main.vetorNumeros.length && Main.vetorNumeros[indexNumber + 1] != null) {
                        Main.vetorNumeros[indexNumber + 1].hideLeft();
                    }
                }
            } catch (NullPointerException ex) {
                
            }
            
            
            for (int i = Main.vectorSize; i > indexNumber; i--) {

                Main.vetorNumeros[i] = Main.vetorNumeros[i - 1];
                Main.moveVectorObjectRight(Main.vetorNumeros, i, (i * 0.25f) - 0.4f);
                
                
            }

            BranchGroup branchGroup = new BranchGroup();

            Sphere sphere = new Sphere(Main.raio, Main.criarApp());
            sphere.setCapability(Sphere.ENABLE_APPEARANCE_MODIFY);
            Transform3D tfSphere = new Transform3D();
            checkElementPosition(indexNumber);
            boolean move = false;
            if (Main.vectorSize == 0) {
                tfSphere.setTranslation(new Vector3f(elementPosition.x, elementPosition.y, elementPosition.z));

            } else {
                tfSphere.setTranslation(new Vector3f(elementPosition.x, elementPosition.y - 0.5f, elementPosition.z));
                move = true;
            }

            TransformGroup tgSphere = new TransformGroup(tfSphere);
            tgSphere.addChild(sphere);


            Box lBox = new Box(0.1f, 0.02f, 0.02f, Main.criarAppCustom());
            Box rBox = new Box(0.1f, 0.02f, 0.02f, Main.criarAppCustom());


            Transform3D tfLBox = new Transform3D();
            tfLBox.setTranslation(new Vector3f(-Main.raio, 0.1f, 0));
            Transform3D tfRBox = new Transform3D();
            tfRBox.setTranslation(new Vector3f(Main.raio, -1.0f, 0));

            
            
            TransformGroup tgLBox = new TransformGroup(tfLBox);
            TransformGroup tgRBox = new TransformGroup(tfRBox);
            tgLBox.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
            tgLBox.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            tgRBox.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
            tgRBox.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            
            Cone coneLeft = new Cone(0.04f, 0.1f, Main.criarAppCustom());
            Cone coneRight = new Cone(0.04f, 0.1f, Main.criarAppCustom());
            
            Transform3D tfLCone = new Transform3D();
            tfLCone.rotZ(Math.toRadians(-90));
            tfLCone.setTranslation(new Vector3f(-Main.raio + 0.14f, 0.00f, 0));
            
            Transform3D tfRCone = new Transform3D();
            tfRCone.rotZ(Math.toRadians(90));
            tfRCone.setTranslation(new Vector3f(Main.raio - 0.14f, -0.00f, 0));
            
            TransformGroup tgLCone = new TransformGroup(tfLCone);
            TransformGroup tgRCone = new TransformGroup(tfRCone);
            tgLCone.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
            tgLCone.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            tgRCone.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
            tgRCone.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            
            tgLCone.addChild(coneLeft);
            tgRCone.addChild(coneRight);
            

            tgLBox.addChild(lBox);
            tgRBox.addChild(rBox);
            tgLBox.addChild(tgLCone);
            tgRBox.addChild(tgRCone);
           

            tgSphere.addChild(tgLBox);
            tgSphere.addChild(tgRBox);
            branchGroup.addChild(tgSphere);

            Main.vetorNumeros[indexNumber] = new Sorting.Number(number, tgSphere, tgLBox, tgRBox);
            
            if (Main.vectorSize == 0) {
                
                Main.highlightsText("  se (head == tail) {\n", Main.textoListaAdd);
                Main.highlightsText("    head.setProximo(novo No(valor, head, tail));\n", Main.textoListaAdd);
                Main.highlightsText("    tail.setAnterior(head.proximo);\n", Main.textoListaAdd);
                Main.textPane.getStyledDocument().setCharacterAttributes(0, Main.textoListaAdd.length(), Main.defaultText, true);
                Main.textPane2.setText("tamanho_lista = " + Main.vectorSize);
                
            } else {
                
                Main.highlightsText("    No elemento = head;\n", Main.textoListaAdd);
                Main.highlightsText("    para (int i = 0; i < indice; i++) {\n", Main.textoListaAdd);
                Main.highlightsText("      elemento = elemento.getProximo();\n", Main.textoListaAdd);
            }
            
            
            Main.su.addBranchGraph(branchGroup);

            Main.vetorNumeros[indexNumber].hideRight();
            Main.vetorNumeros[indexNumber].hideLeft();
            
            
            if (Main.vectorSize != 0) {
                Main.highlightsText("    No elemento2 = elemento.getProximo();\n", Main.textoListaAdd);
            }
            
            
            if (move == true) {
                Main.moveVectorObjectUp(Main.vetorNumeros, indexNumber, elementPosition.y);
            }

            for (int i = 0; i < Main.vetorNumeros.length; i++) {

                if (Main.vetorNumeros[i] == null) {
                    continue;
                }

                if (i == 0) {
                    Main.vetorNumeros[i].hideLeft();
                    if (Main.vetorNumeros[i + 1] == null) {
                        Main.vetorNumeros[i].hideRight();
                    }
                    if (i == 0 && Main.vetorNumeros[i + 1] != null) {
                        Main.vetorNumeros[i].showRight(elementPosition.y + 0.1f);
                    }
                } else if (i + 1 <= Main.vetorNumeros.length - 1) {
                    if (Main.vetorNumeros[i + 1] == null) {
                        Main.vetorNumeros[i].hideRight();
                        Main.vetorNumeros[i].showLeft(elementPosition.y + 0.1f);
                    } else {
                        Main.vetorNumeros[i].showLeft(elementPosition.y + 0.1f);
                        Main.vetorNumeros[i].showRight(elementPosition.y - 0.1f);
                    }
                } else {
                    Main.vetorNumeros[i].showLeft(elementPosition.y + 0.1f);
                    Main.vetorNumeros[i].showRight(elementPosition.y - 0.1f);
                }

            }
            
            if (Main.vectorSize != 0) {
            Main.highlightsText("    elemento.setProximo(novo No(valor, elemento.getProximo(), elemento);\n", Main.textoListaAdd);
            Main.highlightsText("    elemento2.setAnterior(elemento.getProximo());\n", Main.textoListaAdd);
            }
            
            Main.highlightsText("  tamanho_lista++;\n", Main.textoListaAdd);
            Main.vectorSize++;
            
            Main.textPane.getStyledDocument().setCharacterAttributes(0, Main.textoListaAdd.length(), Main.defaultText, true);
            Main.textPane2.setText("tamanho_lista = " + Main.vectorSize);
        }

    }

    public static void popElement() {

        Main.textPane.setText(Main.textoListaRemove);
        String indexString = "";
        int indexNumber = -1;

        while (indexNumber < 0 || indexNumber > 9) {
            indexString = JOptionPane.showInputDialog("Qual a posição do número à ser removido? Capacidade atual: " + Main.vectorCapacity);

            if (indexString == null || indexString.equals("")) {
            } else {
                indexNumber = Integer.parseInt(indexString);
            }

        }

        Main.highlightsText("  No elemento = head;\n", Main.textoListaRemove);
        
        Main.highlightsText("  se (indice > 0 || indice > tamanho_vetor - 1) {\n", Main.textoListaRemove);
        if (indexNumber < 0 || indexNumber >= Main.vectorSize) {
            Main.highlightsText("    Erro: Indice fora da lista!\n", Main.textoListaRemove);
            JOptionPane.showMessageDialog(null, "O índice não está dentro dos limites da lista atual.");
            Main.textPane.getStyledDocument().setCharacterAttributes(0, Main.textoListaRemove.length(), Main.defaultText, true);

        } else {
            
            if (indexNumber == 0) {
                Main.highlightsText("  se (indice == 0) {\n", Main.textoListaRemove);
                Main.highlightsText("    elemento = head.getProximo();\n", Main.textoListaRemove);
                Main.highlightsText("    head.getProximo().getProximo().setAnterior(head);\n", Main.textoListaRemove);
                Main.highlightsText("    head.setProximo(head.getProximo().getProximo());\n", Main.textoListaRemove);
                
                
            } else {
                
                Main.highlightsText("    para (int i = 0; i < indice; i++) {\n", Main.textoListaRemove);
                Main.highlightsText("      elemento = elemento.getProximo();\n", Main.textoListaRemove);
            
            }
            
            Main.destroySphereGeneric(Main.vetorNumeros, indexNumber);
            
            if (indexNumber - 1 > -1) {
                Main.vetorNumeros[indexNumber - 1].hideRight();
            }
            
            try {
                if (Main.vetorNumeros[indexNumber] != null) {
                    Main.vetorNumeros[indexNumber].hideLeft();
                    
                } else {
                    if (indexNumber + 1 < Main.vetorNumeros.length && Main.vetorNumeros[indexNumber + 1] != null) {
                        Main.vetorNumeros[indexNumber + 1].hideLeft();
                    }
                }
            } catch (NullPointerException ex) {
                
            }
            
            
            for (int i = indexNumber; i < Main.vectorSize; i++) {

                if (i != Main.vectorSize) {

                    Main.moveVectorObjectLeft(Main.vetorNumeros, i, (((i - 1) * 0.25f) - 0.4f));
                    Main.vetorNumeros[i] = Main.vetorNumeros[i + 1];

                }

            }

            for (int i = 0; i < Main.vetorNumeros.length; i++) {

                if (Main.vetorNumeros[i] == null) {
                    continue;
                }

                if (i == 0) {
                    Main.vetorNumeros[i].hideLeft();
                    if (Main.vetorNumeros[i + 1] == null) {
                        Main.vetorNumeros[i].hideRight();
                    }
                    if (i == 0 && Main.vetorNumeros[i + 1] != null) {
                        Main.vetorNumeros[i].showRight(elementPosition.y + 0.1f);
                    }
                } else if (i + 1 <= Main.vetorNumeros.length - 1) {
                    if (Main.vetorNumeros[i + 1] == null) {
                        Main.vetorNumeros[i].hideRight();
                        Main.vetorNumeros[i].showLeft(elementPosition.y + 0.1f);
                    } else {
                        Main.vetorNumeros[i].showLeft(elementPosition.y + 0.1f);
                        Main.vetorNumeros[i].showRight(elementPosition.y - 0.1f);
                    }
                } else {
                    Main.vetorNumeros[i].showLeft(elementPosition.y + 0.1f);
                    Main.vetorNumeros[i].showRight(elementPosition.y - 0.1f);
                }

            }
            if (indexNumber != 0) {
            Main.highlightsText("    elemento.getProximo().getProximo().setAnterior(elemento);\n", Main.textoListaRemove);
            Main.highlightsText("    elemento.setProximo(elemento.getProximo().getProximo());\n", Main.textoListaRemove);
            }
            
            Main.highlightsText("  tamanho_lista--;\n", Main.textoListaRemove);
            
            Main.vectorSize--;
            Main.textPane.getStyledDocument().setCharacterAttributes(0, Main.textoListaRemove.length(), Main.defaultText, true);
            Main.textPane2.setText("tamanho_lista = " + Main.vectorSize);

        }

    }

    public static void topElement() {

        if (Main.numberList.isEmpty()) {

            JOptionPane.showMessageDialog(null, "Não há elementos na lista.");

        } else {

            JOptionPane.showMessageDialog(null, "O elemento do topo da lista é: " + Main.numberList.get(0).getNumber());

        }
    }

    public static void showElements() {

        if (Main.vectorSize == 0 || Main.vetorNumeros.length == 0) {

            JOptionPane.showMessageDialog(null, "Não há elementos na lista.");

        } else {


            String numeros = "{ ";

            for (int i = 0; i < Main.vectorSize; i++) {
                numeros += Main.vetorNumeros[i].getNumber() + " ";
            }
            numeros += "}";

            JOptionPane.showMessageDialog(null, "Elementos: " + numeros);

        }

    }

    public void callListButtons() {


        JFrame frame = new JFrame("List Actions");

        JPanel vectorButtonsPanel = new JPanel(new GridLayout(4, 0));

        JButton addButton = new JButton("Inserir");
        JButton removeButton = new JButton("Retirar");
        JButton lastElementButton = new JButton("IsEmpty");
        JButton showElementsButton = new JButton("List Elements");

        addButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                Thread t = new ThreadAuxiliary(listThread, 1);
                t.start();
            }
        });

        removeButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                Thread t = new ThreadAuxiliary(listThread, 2);
                t.start();
            }
        });

        lastElementButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if (Main.vectorSize > 0) {
                    JOptionPane.showMessageDialog(null, "Falso");
                } else {
                    JOptionPane.showMessageDialog(null, "Verdadeiro");
                }
            }
        });

        showElementsButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                showElements();
            }
        });

        JLabel exitLabel = new JLabel("Para finalizar a execução do vetor, feche esta janela");
        JTextArea exitText = new JTextArea("Para finalizar a execução do vetor, feche esta janela");
        exitText.setEditable(false);
        exitText.setLineWrap(true);
        exitText.setAutoscrolls(true);
        vectorButtonsPanel.add(addButton);
        vectorButtonsPanel.add(removeButton);
        vectorButtonsPanel.add(lastElementButton);
        vectorButtonsPanel.add(showElementsButton);
        frame.add(vectorButtonsPanel);
        frame.setBounds(415, 60, 300, 140);

        frame.addWindowListener(new WindowAdapter() {

            public void windowClosing(WindowEvent e) {

                for (int i = 0; i < Main.vectorSize; i++) {
                    Main.destroySphereGeneric(Main.vetorNumeros, i);
                }

//                removeFix();

                Main.vectorSize = 0;
                Main.isRunning = false;
                Main.clearTexts();
                Main.frame.setEnabled(true);

            }
        });

        frame.setResizable(false);
        frame.setVisible(true);

    }
}
